﻿Shader "Mirrors/Bump Specular"
{
    Properties
    {
        _Color         ("Color", Color) = (1,1,1,1)
        _MainTex       ("Albedo (RGB)", 2D) = "white" {}
        _BumpMap       ("Normal Map", 2D) = "bump" {}
        _NormalScale   ("Normal Scale", Float) = 1
        _SpecularMap   ("Specular Map", 2D) = "white" {}
        _Glossiness    ("Glossiness", Range(0,1)) = 0.5
        _OcclusionMap  ("Occlusion Map", 2D) = "white" {}
        _Occlusion     ("Occlusion Scale", Range(0,1)) = 1
        _SpecularColor ("Specular Color", Color) = (0.2,0.2,0.2,1)
        _EmissionColor ("Emission Color", Color) = (0,0,0,1)

        _DetailAlbedo  ("Detail Albedo(RGB) Mask(A)", 2D) = "black" {}
        _AlbedoBlend   ("Albedo Blend Rate", Range(0,1)) = 0.3
        _DetailBump    ("Detail Bump(RGB) Mask(A)", 2D) = "bump" {}
        _BumpBlend     ("Bump Blend Rate", Range(0,1)) = 0.3

        _ReflectionTex ("Reflection RT", 2D) = "black" {}
        _Distortion    ("Reflective Distortion", Range(0,1)) = 0
    }

    SubShader
    {
        Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Opaque" "Queue"="Geometry" }
        LOD 200

        Pass
        {
            Name "UniversalForward"
            Tags { "LightMode"="UniversalForward" }
            ZWrite On
            Cull Back
            Blend Off

            HLSLPROGRAM
            #pragma vertex   vert
            #pragma fragment frag

            // 尽量少的 URP 关键字，兼容旧版
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _ADDITIONAL_LIGHTS
            #pragma multi_compile_fragment _ _ADDITIONAL_LIGHTS_SHADOWS
            #pragma multi_compile_fragment _ _SHADOWS_SOFT

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes {
                float3 positionOS : POSITION;
                float3 normalOS   : NORMAL;
                float4 tangentOS  : TANGENT;
                float2 uv         : TEXCOORD0;
                float2 uv2        : TEXCOORD1;
            };

            struct Varyings {
                float4 positionCS : SV_POSITION;
                float3 positionWS : TEXCOORD0;
                float3 normalWS   : TEXCOORD1;
                float3 tangentWS  : TEXCOORD2;
                float3 bitanWS    : TEXCOORD3;
                float2 uv         : TEXCOORD4;
                float2 uvDetail   : TEXCOORD5;
                float4 screenPos  : TEXCOORD6;
                float4 shadowCoord: TEXCOORD7;
            };

            CBUFFER_START(UnityPerMaterial)
                float4 _Color;
                float4 _EmissionColor;
                float  _NormalScale;
                float  _Glossiness;
                float  _Occlusion;
                float  _AlbedoBlend;
                float  _BumpBlend;
                float  _Distortion;
                float4 _MainTex_ST, _DetailAlbedo_ST, _DetailBump_ST;
                float4 _SpecularColor;
            CBUFFER_END

            TEXTURE2D(_MainTex);       SAMPLER(sampler_MainTex);
            TEXTURE2D(_BumpMap);       SAMPLER(sampler_BumpMap);
            TEXTURE2D(_DetailAlbedo);  SAMPLER(sampler_DetailAlbedo);
            TEXTURE2D(_DetailBump);    SAMPLER(sampler_DetailBump);
            TEXTURE2D(_SpecularMap);   SAMPLER(sampler_SpecularMap);
            TEXTURE2D(_OcclusionMap);  SAMPLER(sampler_OcclusionMap);
            TEXTURE2D(_ReflectionTex); SAMPLER(sampler_ReflectionTex);

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                VertexPositionInputs p = GetVertexPositionInputs(IN.positionOS);
                VertexNormalInputs   n = GetVertexNormalInputs(IN.normalOS, IN.tangentOS);

                OUT.positionCS = p.positionCS;
                OUT.positionWS = p.positionWS;
                OUT.normalWS   = normalize(n.normalWS);
                OUT.tangentWS  = normalize(n.tangentWS);
                OUT.bitanWS    = normalize(n.bitangentWS);

                OUT.uv       = TRANSFORM_TEX(IN.uv, _MainTex);
                OUT.uvDetail = TRANSFORM_TEX(IN.uv, _DetailAlbedo);

                OUT.screenPos   = ComputeScreenPos(OUT.positionCS);
                // 用世界坐标直接变换到主光阴影坐标
                OUT.shadowCoord = TransformWorldToShadowCoord(p.positionWS);
                return OUT;
            }

            float2 ScreenUV(float4 positionCS)
            {
                float2 uv = positionCS.xy / positionCS.w;
                uv = uv * 0.5 + 0.5;
            #if UNITY_UV_STARTS_AT_TOP
                uv.y = 1.0 - uv.y;
            #endif
                return uv;
            }

            half4 frag(Varyings IN) : SV_Target
            {
                // Tangent-space normal（主 + 细节）
                half3 nTS  = UnpackNormal(SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, IN.uv));
                nTS.xy    *= _NormalScale;
                half3 nTS2 = UnpackNormal(SAMPLE_TEXTURE2D(_DetailBump, sampler_DetailBump, IN.uvDetail));
                nTS = normalize(lerp(nTS, nTS2, _BumpBlend));

                // TBN → 世界
                float3x3 TBN = float3x3(normalize(IN.tangentWS), normalize(IN.bitanWS), normalize(IN.normalWS));
                float3 N = normalize(mul(TBN, nTS));
                float3 V = normalize(GetWorldSpaceViewDir(IN.positionWS));

                // Albedo + Detail
                half4 baseC = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv) * _Color;
                half4 detA  = SAMPLE_TEXTURE2D(_DetailAlbedo, sampler_DetailAlbedo, IN.uvDetail);
                baseC.rgb   = lerp(baseC.rgb, detA.rgb, _AlbedoBlend);

                // Occlusion
                half ao = lerp(1.0h, SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, IN.uv).r, _Occlusion);

                // Specular & Smoothness（Spec 工作流）
                half4 specTex = SAMPLE_TEXTURE2D(_SpecularMap, sampler_SpecularMap, IN.uv);
                half3 F0 = saturate(_SpecularColor.rgb * specTex.rgb);
                half  smooth = saturate(_Glossiness * specTex.a);

                // 主光
                Light mainL = GetMainLight(IN.shadowCoord);
                float3 L = normalize(mainL.direction);
                float3 H = normalize(L + V);
                half NoL = saturate(dot(N, L));
                half NoV = saturate(dot(N, V));
                half VoH = saturate(dot(V, H));

                // 简化高光（近似 PBR 外观）
                half specPow = lerp(8.0h, 2048.0h, smooth);
                half3 specBRDF = F0 * pow(VoH, specPow);
                half3 diffBRDF = baseC.rgb * ao;

                half3 direct = mainL.color * (diffBRDF * NoL + specBRDF * NoL);

                // 反射 RT（屏幕坐标 + 法线扰动）
                float2 suv = ScreenUV(IN.screenPos);
                suv += nTS.xy * _Distortion;
                half3 refl = SAMPLE_TEXTURE2D(_ReflectionTex, sampler_ReflectionTex, saturate(suv)).rgb;

                // Fresnel（Schlick）
                half3 F = F0 + (1.0h - F0) * pow(1.0h - NoV, 5.0h);

                // 最终：直射 + 自发光 + Fresnel*反射
                half3 color = direct + _EmissionColor.rgb + refl * F;

                return half4(color, 1);
            }
            ENDHLSL
        }
    }
    FallBack Off
}
